package com.example.ecommerce.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.ecommerce.common.exception.BusinessException;
import com.example.ecommerce.dto.LoginRequestDTO;
import com.example.ecommerce.dto.LoginResponseDTO;
import com.example.ecommerce.dto.RoleDTO;
import com.example.ecommerce.dto.UserDTO;
import com.example.ecommerce.entity.User;
import com.example.ecommerce.mapper.UserMapper;
import com.example.ecommerce.service.MenuService;
import com.example.ecommerce.service.RoleService;
import com.example.ecommerce.service.UserRoleService;
import com.example.ecommerce.service.UserService;
import com.example.ecommerce.util.JwtUtils;
import io.jsonwebtoken.Jwts;
import org.modelmapper.ModelMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

@Service
@Transactional(rollbackFor = Exception.class)
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private RoleService roleService;

    @Autowired
    private UserRoleService userRoleService;

//    @Autowired
//    private PasswordEncoder passwordEncoder;

    @Autowired
    private ModelMapper modelMapper;

    @Autowired
    private HttpServletRequest request;

    @Autowired
    private JwtUtils jwtUtil;

    @Autowired
    private MenuService menuService;

    @Override
    public User login(LoginRequestDTO loginRequest){
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getUsername, loginRequest.getUsername())
        .eq(User::getPassword, loginRequest.getPassword())
                .eq(User::getStatus, 1);
        return userMapper.selectOne(queryWrapper);
    }


    @Override
    public UserDTO getUserById(Long id) {
        User user = getById(id);
        if (user == null) {
            throw new BusinessException("用户不存在");
        }

        UserDTO userDTO = modelMapper.map(user, UserDTO.class);
        // 获取用户角色
        userDTO.setRoles(roleService.getRolesByUserId(id));
        userDTO.setMenus(menuService.getUserMenus(id));
        return userDTO;
    }

    @Override
    public Page<UserDTO> getUserList(Integer page, Integer size, String keyword) {
        Page<User> userPage = new Page<>(page, size);

        // 构建查询条件
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        if (StringUtils.hasText(keyword)) {
            queryWrapper.like(User::getUsername, keyword)
                    .or()
                    .like(User::getNickname, keyword)
                    .or()
                    .like(User::getEmail, keyword)
                    .or()
                    .like(User::getPhone, keyword);
        }

        // 执行分页查询
        Page<User> result = userMapper.selectPage(userPage, queryWrapper);

        // 转换为DTO
        List<UserDTO> userDTOs = result.getRecords().stream()
                .map(user -> {
                    UserDTO dto = modelMapper.map(user, UserDTO.class);
                    dto.setRoles(roleService.getRolesByUserId(user.getId()));
                    return dto;
                })
                .collect(Collectors.toList());

        Page<UserDTO> dtoPage = new Page<>(result.getCurrent(), result.getSize(), result.getTotal());
        dtoPage.setRecords(userDTOs);

        return dtoPage;
    }

    @Override
    public UserDTO createUser(UserDTO userDTO) {
        // 验证用户名是否重复
        if (checkUsernameExists(userDTO.getUsername(), null)) {
            throw new BusinessException("用户名已存在");
        }

        // 验证邮箱是否重复
        if (StringUtils.hasText(userDTO.getEmail()) &&
                checkEmailExists(userDTO.getEmail(), null)) {
            throw new BusinessException("邮箱已被使用");
        }

        // 验证手机号是否重复
        if (StringUtils.hasText(userDTO.getPhone()) &&
                checkPhoneExists(userDTO.getPhone(), null)) {
            throw new BusinessException("手机号已被使用");
        }

        User user = modelMapper.map(userDTO, User.class);
        // 加密密码
//        user.setPassword(passwordEncoder.encode(user.getPassword()));
        user.setPassword(user.getPassword());
        user.setCreatedAt(LocalDateTime.now());
        user.setUpdatedAt(LocalDateTime.now());

        // 保存用户
        save(user);

        // 保存用户角色关系
        if (userDTO.getRoles() != null && !userDTO.getRoles().isEmpty()) {
            List<Long> roleIds = userDTO.getRoles().stream()
                    .map(RoleDTO::getId)
                    .collect(Collectors.toList());
            userRoleService.assignRoles(user.getId(), roleIds);
        }

        return getUserById(user.getId());
    }

    @Override
    public UserDTO updateUser(Long id, UserDTO userDTO) {
        User existingUser = getById(id);
        if (existingUser == null) {
            throw new BusinessException("用户不存在");
        }

        // 验证用户名是否重复
        if (!existingUser.getUsername().equals(userDTO.getUsername()) &&
                checkUsernameExists(userDTO.getUsername(), id)) {
            throw new BusinessException("用户名已存在");
        }

        // 验证邮箱是否重复
        if (StringUtils.hasText(userDTO.getEmail()) &&
                !userDTO.getEmail().equals(existingUser.getEmail()) &&
                checkEmailExists(userDTO.getEmail(), id)) {
            throw new BusinessException("邮箱已被使用");
        }

        // 验证手机号是否重复
        if (StringUtils.hasText(userDTO.getPhone()) &&
                !userDTO.getPhone().equals(existingUser.getPhone()) &&
                checkPhoneExists(userDTO.getPhone(), id)) {
            throw new BusinessException("手机号已被使用");
        }

        User user = modelMapper.map(userDTO, User.class);
        user.setId(id);
        user.setUpdatedAt(LocalDateTime.now());
        // 如果密码为空，保持原密码不变
        if (!StringUtils.hasText(user.getPassword())) {
            user.setPassword(existingUser.getPassword());
        } else {
//            user.setPassword(passwordEncoder.encode(user.getPassword()));
            user.setPassword(user.getPassword());
        }


        // 更新用户
        updateById(user);

        // 更新用户角色关系
        if (userDTO.getRoles() != null) {
            List<Long> roleIds = userDTO.getRoles().stream()
                    .map(RoleDTO::getId)
                    .collect(Collectors.toList());
            userRoleService.assignRoles(id, roleIds);
        }

        return getUserById(id);
    }

    @Override
    public void deleteUser(Long id) {
        if (!exists(id)) {
            throw new BusinessException("用户不存在");
        }

        // 删除用户角色关系
        userRoleService.deleteByUserId(id);

        // 删除用户
        removeById(id);
    }

    public boolean exists(Long id) {
        return getById(id) != null;
    }

    @Override
    public UserDTO getCurrentUser() {
        // 从请求头中获取token
        String token = request.getHeader("Authorization");
        if (StringUtils.isEmpty(token)) {
            throw new BusinessException("未登录");
        }
        
        // 从token中获取用户ID
        Long userId = getUserIdFromToken(token);
//        Long userId =1L;
        if (userId == null) {
            throw new BusinessException("无效的token");
        }
        
        // 获取用户信息
        return getUserById(userId);
    }

    private Long getUserIdFromToken(String token) {
        try {
            return jwtUtil.getUserIdFromRequest();
        } catch (Exception e) {
            throw new BusinessException("无效的token");
        }
    }

    private boolean checkUsernameExists(String username, Long excludeId) {
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getUsername, username);
        if (excludeId != null) {
            queryWrapper.ne(User::getId, excludeId);
        }
        return count(queryWrapper) > 0;
    }

    private boolean checkEmailExists(String email, Long excludeId) {
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getEmail, email);
        if (excludeId != null) {
            queryWrapper.ne(User::getId, excludeId);
        }
        return count(queryWrapper) > 0;
    }

    private boolean checkPhoneExists(String phone, Long excludeId) {
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getPhone, phone);
        if (excludeId != null) {
            queryWrapper.ne(User::getId, excludeId);
        }
        return count(queryWrapper) > 0;
    }
}